from django.shortcuts import render, redirect
from django.db.models import Sum, F
from django.http import JsonResponse
from .models import ProductInventoryLog, MaterialInventoryLog, ProductMaterialRelation
from .forms import (
    ProductInboundForm, MaterialInboundForm,
    ProductOutboundForm, StockCalculationForm
)
from django.contrib import messages
from django.views.decorators.http import require_http_methods
import json
from datetime import date


def home(request):
    product_count = ProductInventoryLog.objects.values('sku').distinct().count()
    total_product_boxes = ProductInventoryLog.objects.aggregate(total_boxes=Sum('box_count'))['total_boxes']
    total_product_pcs = ProductInventoryLog.objects.aggregate(total_pcs=Sum(F('box_count')*F('box_spec')))['total_pcs']
    material_count = MaterialInventoryLog.objects.values('sku').distinct().count()
    total_material_pcs = MaterialInventoryLog.objects.aggregate(total_pcs=Sum('pcs_count'))['total_pcs']
    context = {
        'product_count': product_count,
        'total_product_boxes': total_product_boxes,
        'total_product_pcs': total_product_pcs,
        'material_count': material_count,
        'total_material_pcs': total_material_pcs,
    }

    return render(request, 'erp/home.html', context=context)


def product_inventory(request):
    search_query = request.GET.get('search', '')

    if search_query:
        # 按SKU模糊查询
        inventory_data = ProductInventoryLog.objects.filter(
            sku__icontains=search_query
        ).order_by('sku', 'box_spec').values('sku', 'box_spec').annotate(
            total_pcs=Sum('box_count') * F('box_spec'),
            total_boxes=Sum('box_count')
        )
    else:
        inventory_data = ProductInventoryLog.objects.order_by('sku', 'box_spec').values(
            'sku', 'box_spec'
        ).annotate(
            total_pcs=Sum('box_count') * F('box_spec'),
            total_boxes=Sum('box_count')
        )

    # 按SKU分组，合并不同箱规的数据
    grouped_data = {}
    for item in inventory_data:
        sku = item['sku']
        if sku not in grouped_data:
            grouped_data[sku] = {
                'sku': sku,
                'total_pcs': 0,
                'total_boxes': 0,
                'box_details': []
            }
        if item['total_pcs'] > 0:
            grouped_data[sku]['total_pcs'] += item['total_pcs']
            grouped_data[sku]['total_boxes'] += item['total_boxes']
            grouped_data[sku]['box_details'].append(
                f"{item['box_spec']}*{item['total_boxes']}箱"
            )

    context = {
        'inventory_data': grouped_data.values(),
        'search_query': search_query
    }
    return render(request, 'erp/product_inventory.html', context)


def material_inventory(request):
    search_query = request.GET.get('search', '')

    if search_query:
        inventory_data = MaterialInventoryLog.objects.filter(
            sku__icontains=search_query
        ).order_by('sku').values('sku').annotate(total_pcs=Sum('pcs_count'))
    else:
        inventory_data = MaterialInventoryLog.objects.order_by('sku').values(
            'sku'
        ).annotate(total_pcs=Sum('pcs_count'))

    context = {
        'inventory_data': inventory_data,
        'search_query': search_query
    }
    return render(request, 'erp/material_inventory.html', context)


def product_inbound(request):
    today = date.today().strftime('%Y-%m-%d')
    if request.method == 'POST':
        form_data = json.loads(request.POST.get('form_data'))
        print('this is the form_data of productinbound', form_data)
        for item in form_data:
            form = ProductInboundForm(item)
            if form.is_valid():
                log = form.save(commit=False)
                log.save()

                # 计算物料消耗并更新物料库存
                calculate_material_usage(log.sku, log.box_count * log.box_spec)
        return redirect('product_inbound')
        #return JsonResponse({'success': True})

    # 初始化1个空表单
    forms = [ProductInboundForm() for _ in range(1)]

    # 获取所有产品SKU用于下拉框
    sku_choices = ProductMaterialRelation.objects.values_list(
        'product_sku', flat=True
    ).order_by('product_sku').distinct()

    context = {
        'forms': forms,
        'sku_choices': sku_choices,
        'sku_choices_json': json.dumps(list(sku_choices)),
        'today': today,
    }
    return render(request, 'erp/product_inbound.html', context)


def material_inbound(request):
    today = date.today().strftime('%Y-%m-%d')
    if request.method == 'POST':
        form_data = json.loads(request.POST.get('form_data'))

        for item in form_data:
            form = MaterialInboundForm(item)
            if form.is_valid():
                log = form.save(commit=False)
                log.save()
        return redirect('material_inbound')
        #return JsonResponse({'success': True})

    # 初始化1个空表单
    forms = [MaterialInboundForm() for _ in range(1)]

    # 获取所有物料SKU用于下拉框
    sku_choices = ProductMaterialRelation.objects.values_list(
        'material_sku', flat=True
    ).order_by('material_sku').distinct()

    context = {
        'forms': forms,
        'sku_choices': sku_choices,
        'sku_choices_json': json.dumps(list(sku_choices)),
        'today': today,
    }
    return render(request, 'erp/material_inbound.html', context)


def product_outbound(request):
    today = date.today().strftime('%Y-%m-%d')
    if request.method == 'POST':
        form_data = json.loads(request.POST.get('form_data'))

        for item in form_data:
            form = ProductOutboundForm(item)
            if form.is_valid():
                sku = form.cleaned_data['sku']
                box_spec = form.cleaned_data['box_spec']
                outbound_boxes = form.cleaned_data['outbound_boxes']
                outbound_date = form.cleaned_data['date']

                if outbound_boxes > 0:
                    # 创建出库记录
                    ProductInventoryLog.objects.create(
                        sku=sku,
                        box_spec=box_spec,
                        box_count=-outbound_boxes,
                        date=outbound_date,
                        remark="产品出库"
                    )

        return JsonResponse({'success': True})

    # 获取当前库存数据
    inventory_data = ProductInventoryLog.objects.values(
        'sku', 'box_spec'
    ).order_by('sku', 'box_spec').annotate(total_boxes=Sum('box_count')).filter(
        total_boxes__gt=0
    )

    forms = []
    for item in inventory_data:
        form = ProductOutboundForm(initial={
            'sku': item['sku'],
            'box_spec': item['box_spec'],
            'total_boxes': item['total_boxes'],
            'outbound_boxes': 0
        })
        forms.append(form)

    context = {
        'forms': forms,
        'today': today,
    }
    return render(request, 'erp/product_outbound.html', context)




def calculate_material_usage(product_sku, pcs_count):
    # 获取产品物料关系
    material_relations = ProductMaterialRelation.objects.filter(
        product_sku=product_sku
    )

    for relation in material_relations:
        # 计算物料消耗
        material_usage = pcs_count * relation.material_quantity

        # 创建物料消耗记录
        MaterialInventoryLog.objects.create(
            sku=relation.material_sku,
            pcs_count=-material_usage,
            date=date.today(),
            remark=f"生产{product_sku}消耗"
        )


def update_material_inventory(request):

    if request.method == 'POST':
        sku = request.POST.get('sku')
        current_pcs = int(request.POST.get('current_pcs', 0))
        new_pcs = int(request.POST.get('new_pcs', 0))

        if not sku:
            messages.error(request, '请选择要更新的物料')
            return redirect('material_inventory')

        difference = new_pcs - current_pcs

        if difference == 0:
            messages.warning(request, f'物料 {sku} 库存未变化')
            return redirect('material_inventory')

        # 创建库存调整记录
        MaterialInventoryLog.objects.create(
            sku=sku,
            pcs_count=difference,
            date=date.today(),
            remark=f"库存调整: {'增加' if difference > 0 else '减少'} {abs(difference)}"
        )

        messages.success(request, f'成功更新物料 {sku} 库存')
        return redirect('material_inventory')

    return redirect('material_inventory')


def stock_calculation(request):
    # 获取所有产品SKU用于下拉框
    product_skus = ProductMaterialRelation.objects.values_list(
        'product_sku', flat=True).distinct()

    if request.method == 'POST':
        try:
            form_data = json.loads(request.POST.get('form_data', '[]'))
            results = []
            material_aggregate = {}

            for item in form_data:
                product_sku = item.get('product_sku')
                required_quantity = int(item.get('required_quantity', 0))

                # 计算当前产品库存
                product_stock = ProductInventoryLog.objects.filter(
                    sku=product_sku
                ).aggregate(
                    total=Sum(F('box_count') * F('box_spec'))
                )['total'] or 0

                # 计算需要生产的产品数量
                production_needed = max(0, required_quantity - product_stock)

                # 获取产品物料关系
                material_relations = ProductMaterialRelation.objects.filter(
                    product_sku=product_sku
                )

                product_materials = []
                for relation in material_relations:
                    material_required = production_needed * relation.material_quantity

                    # 聚合物料需求
                    if relation.material_sku not in material_aggregate:
                        material_stock = MaterialInventoryLog.objects.filter(
                            sku=relation.material_sku
                        ).aggregate(total=Sum('pcs_count'))['total'] or 0

                        material_aggregate[relation.material_sku] = {
                            'required': 0,
                            'current': material_stock,
                            'shortage': 0
                        }

                    material_aggregate[relation.material_sku]['required'] += material_required

                results.append({
                    'product_sku': product_sku,
                    'required_quantity': required_quantity,
                    'current_stock': product_stock,
                    'production_needed': production_needed,
                })

            # 计算物料缺口
            material_aggregate = dict(sorted(material_aggregate.items()))
            for sku, data in material_aggregate.items():
                data['shortage'] = max(0, data['required'] - data['current'])

            return JsonResponse({
                'success': True,
                'products': results,
                'materials': material_aggregate
            })

        except Exception as e:
            return JsonResponse({
                'success': False,
                'error': str(e)
            })

    context = {
        'product_skus': list(product_skus),
        'sku_choices_json': json.dumps(list(product_skus)),
    }
    return render(request, 'erp/stock_calculation.html', context)